cmake_minimum_required(VERSION 3.16)
project(Fluent_FEM LANGUAGES C CXX)

# 生成 compile_commands.json 便于 IDE 索引
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# 默认构建类型
if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
endif()

# C 语言标准
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)

# C++ 语言标准
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# --- 依赖根目录/库路径（可在配置时覆盖） ---
set(SUPERLU_DIST_ROOT "/home/one/app/superlu_dist-9.1.0" CACHE PATH "Root of SuperLU_DIST installation")
set(METIS_ROOT        "/home/one/app/metis-5.1.0-Int32Double" CACHE PATH "Root of METIS installation")
set(PARMETIS_ROOT     "/home/one/app/parmetis-4.0.3-Int32Double" CACHE PATH "Root of ParMETIS installation")
set(CJSON_ROOT        "/home/one/app/cJSON-1.7.19" CACHE PATH "Root of cJSON installation")
# OpenBLAS 优先使用指定的静态库路径；若不存在则回退 find_library
set(OPENBLAS_LIBRARY  "/usr/lib/x86_64-linux-gnu/libopenblas.a" CACHE FILEPATH "Path to OpenBLAS library or leave empty to auto-detect")

# --- 查找编译器与并行库 ---
find_package(MPI REQUIRED C)
find_package(OpenMP REQUIRED)
# 新增：优先使用 pkg-config 发现依赖
find_package(PkgConfig QUIET)
if(PkgConfig_FOUND)
  pkg_check_modules(PKG_SUPERLU_DIST QUIET superlu_dist)
  pkg_check_modules(PKG_METIS       QUIET metis)
  pkg_check_modules(PKG_PARMETIS    QUIET parmetis)
  pkg_check_modules(PKG_CJSON       QUIET cjson)
  pkg_check_modules(PKG_OPENBLAS    QUIET openblas)
  if(PKG_SUPERLU_DIST_FOUND)
    set(SUPERLU_DIST_LIBRARY     ${PKG_SUPERLU_DIST_LIBRARIES})
    set(SUPERLU_DIST_INCLUDE_DIR ${PKG_SUPERLU_DIST_INCLUDE_DIRS})
  endif()
  if(PKG_METIS_FOUND)
    set(METIS_LIBRARY ${PKG_METIS_LIBRARIES})
  endif()
  if(PKG_PARMETIS_FOUND)
    set(PARMETIS_LIBRARY ${PKG_PARMETIS_LIBRARIES})
  endif()
  if(PKG_CJSON_FOUND)
    set(CJSON_LIBRARY     ${PKG_CJSON_LIBRARIES})
    set(CJSON_INCLUDE_DIR ${PKG_CJSON_INCLUDE_DIRS})
  endif()
  if(PKG_OPENBLAS_FOUND)
    set(OPENBLAS_LIBRARY ${PKG_OPENBLAS_LIBRARIES})
  endif()
endif()

# --- 查找第三方库与头文件（未通过 pkg-config 找到时回退） ---
# SuperLU_DIST
if(NOT SUPERLU_DIST_LIBRARY)
  find_library(SUPERLU_DIST_LIBRARY
    NAMES superlu_dist
    HINTS "${SUPERLU_DIST_ROOT}"
    PATH_SUFFIXES lib lib64
  )
endif()
if(NOT SUPERLU_DIST_INCLUDE_DIR)
  find_path(SUPERLU_DIST_INCLUDE_DIR
    NAMES slu_ddefs.h superlu_dist_config.h
    HINTS "${SUPERLU_DIST_ROOT}"
    PATH_SUFFIXES include
  )
endif()

# METIS & ParMETIS
if(NOT METIS_LIBRARY)
  find_library(METIS_LIBRARY
    NAMES metis
    HINTS "${METIS_ROOT}"
    PATH_SUFFIXES lib lib64
  )
endif()
if(NOT PARMETIS_LIBRARY)
  find_library(PARMETIS_LIBRARY
    NAMES parmetis
    HINTS "${PARMETIS_ROOT}"
    PATH_SUFFIXES lib lib64
  )
endif()

# cJSON
if(NOT CJSON_LIBRARY)
  find_library(CJSON_LIBRARY
    NAMES cjson libcjson
    HINTS "${CJSON_ROOT}"
    PATH_SUFFIXES lib lib64
  )
endif()
if(NOT CJSON_INCLUDE_DIR)
  find_path(CJSON_INCLUDE_DIR
    NAMES cJSON.h
    HINTS "${CJSON_ROOT}"
    PATH_SUFFIXES include include/cjson
  )
endif()

# OpenBLAS 可由显式路径或自动发现提供
if(NOT OPENBLAS_LIBRARY OR NOT EXISTS "${OPENBLAS_LIBRARY}")
  unset(OPENBLAS_LIBRARY CACHE)
  find_library(OPENBLAS_LIBRARY NAMES openblas)
endif()

# --- 校验依赖是否就绪 ---
foreach(var
  SUPERLU_DIST_LIBRARY SUPERLU_DIST_INCLUDE_DIR
  METIS_LIBRARY PARMETIS_LIBRARY
  CJSON_LIBRARY CJSON_INCLUDE_DIR
  OPENBLAS_LIBRARY
)
  if(NOT ${var})
    message(FATAL_ERROR "Missing ${var}. Please set corresponding *_ROOT or OPENBLAS_LIBRARY.")
  endif()
endforeach()

# --- 源文件列表（与原 Makefile 对齐） ---
set(SOURCES
  main.c
  prepocess.c
  global_varible.c
  post_prepocess.c
  FEM_compute.c
  para.c
  solver.c
)

add_executable(MTSZ ${SOURCES})

# 头文件路径（来自原 Makefile 中的 -I）
target_include_directories(MTSZ PRIVATE
  ${SUPERLU_DIST_INCLUDE_DIR}
  ${CJSON_INCLUDE_DIR}
  ${CJSON_INCLUDE_DIR}/cjson
)

# OpenMP & MPI & 第三方库链接（与原 Makefile 保持一致）
target_link_libraries(MTSZ PRIVATE
  MPI::MPI_C
  OpenMP::OpenMP_C
  ${SUPERLU_DIST_LIBRARY}
  ${OPENBLAS_LIBRARY}
  ${METIS_LIBRARY}
  ${PARMETIS_LIBRARY}
  ${CJSON_LIBRARY}
)